﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Hiro.Interfaces;
using Hiro.Loaders.Interfaces;
using Hiro.ActivationPoints.Interfaces;

namespace Hiro.Loaders
{
    internal class ServiceResolver : IServiceResolver
    {
        public IEnumerable<IService> Resolve(Type serviceType, IEnumerable<ITypeActivationPoint> activationPoints)
        {
            // The first activation point will be the default implementation
            // for the dependency
            var points = new Queue<ITypeActivationPoint>(activationPoints);
            var defaultItem = points.First();

            var typeName = serviceType.Name ?? string.Empty;
            if (serviceType.IsInterface && typeName.Length > 1 && typeName.ToUpper().StartsWith("I"))
            {
                // Use the type activation point with the implementation type name
                // with a suffix that matches the interface name without the 'I' prefix
                var targetName = typeName.Substring(1);
                var match = (from type in activationPoints
                             where type.TargetType.Name == targetName
                             select type).FirstOrDefault();

                if (match != null)
                    defaultItem = match;
            }

            var defaultDependency = new Dependency(string.Empty, serviceType);
            var defaultService = new Service(defaultDependency, defaultItem);

            var results = new List<IService> { defaultService };
            while (points.Count > 0)
            {
                var currentPoint = points.Dequeue();
                var implementingType = currentPoint.TargetType;

                // By default, each dependency will be named after the implementing type
                var serviceName = implementingType.Name;
                var dependency = new Dependency(serviceName, serviceType);

                results.Add(new Service(dependency, currentPoint));
            }

            return results;
        }
    }
}
